/*
 * Project: Sudoku Explainer
 * Copyright (C) 2006-2007 Nicolas Juillerat
 * 
 * Project: Sudoku Hint Engine for Android
 * Copyright (C) 2010-2013 Emanuel Moecklin
 * 
 * Available under the terms of the Lesser General Public License (LGPL)
 */
package com.onegravity.sudoku.solver.core;

import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import com.onegravity.sudoku.solver.HintType;
import com.onegravity.sudoku.solver.data.Cell;
import com.onegravity.sudoku.solver.data.Grid;
import com.onegravity.sudoku.solver.data.ImmutableCell;
import com.onegravity.sudoku.solver.data.Region;

/**
 * Abstract class for hints that allow the direct placement of a value
 * in a cell of the sudoku grid.
 */
public abstract class DirectHint extends Hint {

	private static final long serialVersionUID = 8771684843294700616L;
	
    private Region region;	// The concerned region, if any
    private Cell cell;		// The cell that can be filled
    private int value;		// The value that can be put in the cell
    private Collection<Cell> selectedCells;
    private Map<Cell, BitSet> selectedPotentials;
    
    /**
     * Create a new hint
     * @param rule the rule that discovered the hint
     * @param region the region for which the hint is applicable,
     * or <tt>null</tt> if irrelevant
     * @param cell the cell in which a value can be placed
     * @param value the value that can be placed in the cell
     */
    public DirectHint(Region region, Cell cell, int value, Collection<Cell> selectedCells, Map<Cell, BitSet> selectedPotentials) {
        this.region = region;
        this.cell = cell;
        this.value = value;
        this.selectedCells = selectedCells;
        this.selectedPotentials = selectedPotentials; 
    }

	@Override
	public Cell getCell(HintType hintType) {
		return this.cell;
   }

    @Override
    public int getValue() {
        return this.value;
    }

    @Override
    public Region[] getRegions(HintType hintType) {
        return (region==null) ? null : new Region[] {this.region};
    }

	@Override
	public Collection<Cell> getSelectedCells(HintType hintType) {
		return selectedCells;
	}

	@Override
	public Map<Cell, BitSet> getSelectedPotentials(HintType hintType, int viewNum) {
		return selectedPotentials;
	}

	@Override
	public Map<ImmutableCell, BitSet> getRemovedPotentials(HintType hintType) {
		return Collections.emptyMap();
	}

    @Override
    public Grid apply() {
        cell.setValueAndCancel(value, cell.isGiven());
        return cell.getGrid();
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof DirectHint)) return false;
        DirectHint other = (DirectHint)o;
        return this.cell.equals(other.cell) && this.value == other.value;
    }

    @Override
    public int hashCode() {
        return this.cell.hashCode() ^ this.value;
    }

    @Override
    public String toString() {
        return ((region==null) ? "" : region.toFullString()) + ": " + cell.toString() + ": " + value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }

}